package cz.spock.core.service;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.objectify.Key;

import cz.spock.core.entity.Account;
import cz.spock.core.entity.acl.AccountRole;
import cz.spock.core.entity.acl.Acl;
import cz.spock.core.entity.acl.AclDefault;
import cz.spock.core.entity.acl.Role;

/**
 * provides all logic for creating and managing roles and access rights
 * 
 * @author miso
 *
 */
public class ACLService extends BaseService {
    
    Role createRole() {
        return null;
    }
    
    Acl setRights(Key<Account> account, Key entity, int rights) {
        return null;
    }
    
    /**
     * returns true only if this account is owner of given entity
     * @param account
     * @param entity
     * @return
     */
    public boolean isOwner(Key<Account> account, Key entity) {
        AclDefault a = dao.ofy().query(AclDefault.class).filter("entity", entity).get();
        if(a == null) {
            // TODO report problem
            return false;
        }
        if(a.getOwner().equals(account)) {
            return true;            
        }
        return false;
    }
    
    /**
     * returns true only if given account has read rights on given entity or if account owns this entity
     * 
     * permissive mode is used - one positive result means that true will be returned
     * (dismissive mode = all results must be true, otherwise false is returned)
     * 
     * @param account
     * @param entity
     * @return
     */
    public boolean canRead(Key<Account> account, Key entity) {
        List<Key<Role>> roles = this.getRoleKeys(account);
        // check for owner
        if(this.isOwner(account, entity)) {
            return true;
        }
        boolean found = false;
        Acl a = null;
        a = dao.ofy().query(Acl.class).filter("entity", entity).filter("account", account).get();
        // check found and make access control
        if(a != null) {
            found = true;
            if(a.getRights() >= 4) return true;
        }
        for(Key<Role> r:roles) {
            a = dao.ofy().query(Acl.class).filter("entity", entity).filter("role", r).get();
            // check found and make access control
            if(a != null) {
                found = true;
                if(a.getRights() >= 4) return true;
            }
        }
        // if found return false
        if(found) return false;
        // else use default acl
        AclDefault ad = dao.ofy().query(AclDefault.class).filter("entity", entity).get();
        if(ad == null) {
            // TODO report error
            return false;
        }
        if(ad.getRights() >= 4) return true;
        return false;
    }
    

    /**
     * returns all role Keys for given account
     * 
     * @param account
     * @return
     */
    public List<Key<Role>> getRoleKeys(Key<Account> account) {
        List<AccountRole> accountRoles = dao.ofy().query(AccountRole.class).filter("account", account).list();
        List<Key<Role>> roleKeys = new ArrayList<Key<Role>>();
        for(AccountRole ar:accountRoles) {
            roleKeys.add(ar.getRole());
        }
        return roleKeys;
    }
    
    /**
     * returns all roles for given account
     * 
     * @param account
     * @return
     */
    public List<Role> getRoles(Key<Account> account) {
        List<AccountRole> accountRoles = dao.ofy().query(AccountRole.class).filter("account", account).list();
        List<Role> roles = new ArrayList<Role>();
        for(AccountRole ar:accountRoles) {
            roles.add(dao.ofy().get(ar.getRole()));
        }
        return roles;
    }
    
   

}
